package org.chartsy.vzo; import java.awt.Color; import java.awt.Graphics2D; import java.awt.Rectangle; import java.awt.Stroke; import java.awt.geom.Line2D; import java.text.DecimalFormat; import java.util.LinkedHashMap; import org.chartsy.main.ChartFrame; import org.chartsy.main.chart.Indicator; import org.chartsy.main.data.DataItem; import org.chartsy.main.data.Dataset; import org.chartsy.main.utils.DefaultPainter; import org.chartsy.main.utils.Range; import org.chartsy.main.utils.SerialVersion; import org.chartsy.main.utils.StrokeGenerator; import org.openide.nodes.AbstractNode; /** * * @author Viorel */ public class VolumeZoneOscillator extends Indicator { private static final long serialVersionUID = SerialVersion.APPVERSION; public static final String VZO = "vzo"; private IndicatorProperties properties; private Color green = new Color(0x73880A); private Color red = new Color(0xCC0000); public VolumeZoneOscillator() { super(); properties = new IndicatorProperties(); } @Override public String getName() { return "VolumeZoneOscillator"; } @Override public String getLabel() { return properties.getLabel() + " (" + properties.getPeriod() + ")"; } @Override public String getPaintedLabel(ChartFrame cf) { return getLabel(); } @Override public Indicator newInstance() { return new VolumeZoneOscillator(); } @Override public LinkedHashMap getHTML(ChartFrame cf, int i) { LinkedHashMap ht = new LinkedHashMap(); DecimalFormat df = new DecimalFormat("#,##0.00"); double[] values = getValues(cf, i); String[] labels = {"VZO:"}; ht.put(getLabel(), " "); if (values.length > 0) { Color[] colors = getColors(); for (int j = 0; j < values.length; j++) ht.put(getFontHTML(colors[j], labels[j]), getFontHTML(colors[j], df.format(values[j]))); } return ht; } @Override public Range getRange(ChartFrame cf) { return new Range(-100, 100); } @Override public void paint(Graphics2D g, ChartFrame cf, Rectangle bounds) { Dataset d = visibleDataset(cf, VZO); if (d != null) { if (maximized) { Range range = getRange(cf); paintConstLine(g, cf, range, bounds, green, StrokeGenerator.getStroke(8), 60); paintConstLine(g, cf, range, bounds, green, StrokeGenerator.getStroke(0), 40); paintConstLine(g, cf, range, bounds, Color.gray, StrokeGenerator.getStroke(0), 15); paintConstLine(g, cf, range, bounds, Color.gray, StrokeGenerator.getStroke(0), -5); paintConstLine(g, cf, range, bounds, red, StrokeGenerator.getStroke(0), -40); paintConstLine(g, cf, range, bounds, red, StrokeGenerator.getStroke(8), -60); DefaultPainter.line(g, cf, range, bounds, d, properties.getColor(), properties.getStroke()); } } } private void paintConstLine(Graphics2D g, ChartFrame cf, Range range, Rectangle bounds, Color color, Stroke stroke, double value) { Stroke old = g.getStroke(); g.setPaint(color); if (stroke != null) g.setStroke(stroke); double y = cf.getChartData().getY(value, bounds, range, false); g.draw(new Line2D.Double(bounds.getMinX(), y, bounds.getMaxX(), y)); g.setStroke(old); } @Override public void calculate() { int period = properties.getPeriod(); Dataset initial = getDataset(); Dataset vzo = Dataset.EMPTY(initial.getItemsCount()); Dataset r = Dataset.EMPTY(initial.getItemsCount()); for (int i = 1; i < initial.getItemsCount(); i++) { double v = ( initial.getCloseAt(i) > initial.getCloseAt(i-1) ) ? initial.getVolumeAt(i) : -1 * initial.getVolumeAt(i); r.setDataItem(i, new DataItem(initial.getTimeAt(i), v)); } Dataset vp = Dataset.EMA(r, period); Dataset tv = Dataset.EMA(initial, period); for (int i = 0; i < initial.getItemsCount(); i++) { if (vp.getDataItem(i) != null && tv.getDataItem(i) != null) { double v = 100 * ( vp.getCloseAt(i) / tv.getVolumeAt(i) ); vzo.setDataItem(i, new DataItem(initial.getTimeAt(i), v)); } } addDataset(VZO, vzo); } @Override public boolean hasZeroLine() { return true; } @Override public boolean getZeroLineVisibility() { return true; } @Override public Color getZeroLineColor() { return Color.black; } @Override public Stroke getZeroLineStroke() { return StrokeGenerator.getStroke(0); } @Override public boolean hasDelimiters() { return false; } @Override public boolean getDelimitersVisibility() { return false; } @Override public double[] getDelimitersValues() { return null; } @Override public Color getDelimitersColor() { return null; } @Override public Stroke getDelimitersStroke() { return null; } @Override public Double[] getPriceValues(ChartFrame cf) { return new Double[] {new Double(-60), new Double(-40), new Double(-5), new Double(15), new Double(40), new Double(60)}; } @Override public Color[] getColors() { return new Color[] { properties.getColor() }; } @Override public double[] getValues(ChartFrame cf) { Dataset d = visibleDataset(cf, VZO); if (d != null) { return new double[] {d.getLastClose()}; } return new double[] {}; } @Override public double[] getValues(ChartFrame cf, int i) { Dataset d = visibleDataset(cf, VZO); if (d != null) { return new double[] {d.getCloseAt(i)}; } return new double[] {}; } @Override public boolean getMarkerVisibility() {return properties.getMarker(); } @Override public AbstractNode getNode() {return new IndicatorNode(properties); } }